package com.example.my_gobang.api;

import com.example.my_gobang.game.*;
import com.example.my_gobang.mapper.UserMapper;
import com.example.my_gobang.model.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import javax.annotation.Resource;
import java.io.IOException;

/**
 * Creat with IntelliJ IDEA
 * Description:
 * User:WZW
 * Date:2022-08-22
 * Time:23:42
 */
@Component
public class GameAPI extends TextWebSocketHandler {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private RoomManager roomManager;

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Resource
    private UserMapper userMapper;

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        GameReadyResponse resp = new GameReadyResponse();
        //获取用户信息
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            resp.setOk(false);
            resp.setReason("您尚未登录，请先登录！");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
            return;
        }
        //判定当前用户是否已经进入房间
        Room room = roomManager.getRoomByUserId(user.getUserid());
        if (room == null) {
            resp.setOk(false);
            resp.setReason("用户尚未匹配到房间！");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
            return;
        }

        //判定用户是否多开
        if (onlineUserManager.getFromGameHall(user.getUserid()) != null
                || onlineUserManager.getFromGameRoom(user.getUserid()) != null) {
            // 一个账号，一边在游戏大厅，一边在游戏房间
            resp.setOk(false);
            resp.setReason("repeat connection!");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
            return;
        }

        //设置玩家上线
        onlineUserManager.enterGameRoom(user.getUserid(), session);

        synchronized (room)
        {
            //把两个玩家加入到游戏房间中
            if (room.getUser1() == null) {
                //玩家1尚未加入房间
                //将当前已经连接上websocket的玩家作为user1加入到房间中
                room.setUser1(user);
                //玩家1作为先手方
                room.setWhiteUser(user.getUserid());
                System.out.println("玩家1" + user.getUsername() + "已经准备就绪！");
                return;
            }

            if (room.getUser2() == null) {
                //此时玩家1已经进入房间，当前玩家作为玩家2
                room.setUser2(user);
                System.out.println("玩家2" + user.getUsername() + "已经准备就绪！");
                //当两个玩家都加入成功后，给两个玩家返回响应
                //通知玩家1
                noticeGameReady(room, room.getUser1(), room.getUser2());
                //通知玩家2
                noticeGameReady(room, room.getUser2(), room.getUser1());
                return;
            }
        }

        //若还有其他玩家尝试连接同一个房间，则提示报错
        resp.setOk(false);
        resp.setReason("当前房间已满，不能加入房间！");
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));

    }

    private void noticeGameReady(Room room, User thisUser, User thatUser) throws IOException {
        GameReadyResponse gameReadyResponse = new GameReadyResponse();
        gameReadyResponse.setMessage("gameReady");
        gameReadyResponse.setOk(true);
        gameReadyResponse.setReason("");
        gameReadyResponse.setRoomId(room.getRoomId());
        gameReadyResponse.setThisUserId(thisUser.getUserid());
        gameReadyResponse.setThatUserId(thatUser.getUserid());
        gameReadyResponse.setWhiteUser(room.getUser1().getUserid());
        WebSocketSession webSocketSession = onlineUserManager.getFromGameRoom(thisUser.getUserid());
        webSocketSession.sendMessage(new TextMessage(objectMapper.writeValueAsString(gameReadyResponse)));
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 获取用户信息
        User user = (User) session.getAttributes().get("user");
        if (user == null) {
            GameReadyResponse resp = new GameReadyResponse();
            resp.setOk(false);
            resp.setReason("您尚未登录，请先登录！");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));
            return;
        }
        // 获取房间对象
        Room room = roomManager.getRoomByUserId(user.getUserid());
        // 通过room对象处理请求
        room.putChess(message.getPayload());
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        // 获取用户信息
        User user = (User) session.getAttributes().get("user");
        if (user == null) return;
        WebSocketSession tmpSession = onlineUserManager.getFromGameRoom(user.getUserid());
        if (tmpSession == session) {
            // 删除用户在线信息
            onlineUserManager.exitGameRoom(user.getUserid());
        }
        System.out.println("当前用户" + user.getUsername() + "游戏连接出现出现异常");
        // 通知对手获胜
        noticeThatUserWin(user);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        // 获取用户信息
        User user = (User) session.getAttributes().get("user");
        if (user == null) return;
        WebSocketSession tmpSession = onlineUserManager.getFromGameRoom(user.getUserid());
        if (tmpSession == session) {
            // 删除用户在线信息
            onlineUserManager.exitGameRoom(user.getUserid());
        }
        System.out.println("当前用户" + user.getUsername() + "离开游戏房间");
        // 通知对手获胜
        noticeThatUserWin(user);
    }

    private void noticeThatUserWin(User user) throws IOException {
        // 1.根据当前玩家找到所在房间对象
        Room room = roomManager.getRoomByUserId(user.getUserid());
        if (room == null) {
            System.out.println("当前房间已经释放，无需通知对手！");
            return;
        }
        // 2.根据房间找道对手
        User thatUser = (user == room.getUser1()) ? room.getUser2() : room.getUser1();
        // 3.检查对手在线状态
        WebSocketSession session = onlineUserManager.getFromGameRoom(thatUser.getUserid());
        if (session == null) {
            // 对手也掉线了
            System.out.println("对手也掉线了");
            roomManager.remove(room.getRoomId(), room.getUser1().getUserid(), room.getUser2().getUserid());
            return;
        }
        // 4.构造响应
        GameResponse resp = new GameResponse();
        resp.setMessage("putChess");
        resp.setUserId(thatUser.getUserid());
        resp.setWinner(thatUser.getUserid());
        session.sendMessage(new TextMessage(objectMapper.writeValueAsString(resp)));

        // 5.更新数据
        int winUserId = thatUser.getUserid();
        int loseUserId = user.getUserid();
        userMapper.userWin(winUserId);
        userMapper.userLose(loseUserId);

        // 6.释放房间
        roomManager.remove(room.getRoomId(), room.getUser1().getUserid(), room.getUser2().getUserid());
    }
}
